﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Data.Entity;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Transactions;
using System.Windows.Forms;
using AccManagerKw.Common;
using DataAccess;
using DevExpress.XtraBars.Controls;
using DevExpress.XtraEditors;
using DevExpress.XtraGrid.Views.Grid;
using Model;
using Model.Interfaces;
using Utilities;

namespace AccManagerKw.Inventory
{
    public partial class FrmItemOpStock : FrmBase, ICrud
    {
        private ClsCommonFn _oCommFn = new ClsCommonFn();
        private ClsDataFn _oDataFn = new ClsDataFn();
        private BindingList<ItemStock> _lstItemStock = new BindingList<ItemStock>();
        private long itemId;
        private List<ItemStock> lstOpenStock;
        private long maxStkId;
        public FrmItemOpStock()
        {
            InitializeComponent();
        }

        private void FrmItemOpStock_Shown(object sender, EventArgs e)
        {
            try
            {
                _oCommFn.GroupControl_Setting(gclMain);
                _oCommFn.GroupControl_Setting(gclOpen);

                _oCommFn.GridSetting(gvStock, gcStock);
                _oCommFn.GridSetting(gvStockSearch, gcStockSearch);
                _oDataFn.SetDataSource(ClsGlobalEnums.EDataSourceType.ItemTypes, lucItemTypes, "ItemTypeName", "ItemTypeId");
                _oDataFn.SetDataSource(ClsGlobalEnums.EDataSourceType.Items, repLucItems, "ItemName", "ItemId");
                _oDataFn.SetDataSource(ClsGlobalEnums.EDataSourceType.Stores, lucStores, "StoreName", "StoreId");

                gcStock.DataSource = _lstItemStock;
                SetStockCode();
            }
            catch (Exception ex)
            {
                _oCommFn.TryCatchErrorMsg(ex.Message);
            }
        }

        private void SetStockCode()
        {
            var context = new AccManagerEntities();
            maxStkId = context.ItemStocks.ToList().Count > 0
                                        ? context.ItemStocks.Max(x => x.StockId) + 1 : 1;
            txtStockCode.Text = string.Format("S-{0}", maxStkId);
        }

        private void lucItemTypes_EditValueChanged(object sender, EventArgs e)
        {

            var context = new AccManagerEntities();
            var itemType = (ItemTypeMaster)lucItemTypes.Properties.View.GetFocusedRow();
            if (itemType != null)
                if (itemType.ItemTypeId != -1)
                    repLucItems.DataSource = context.ItemMasters.Where(x => x.ItemTypeId == itemType.ItemTypeId).ToList();
                else
                    repLucItems.DataSource = context.ItemMasters.ToList();
        }
        private void repLucItems_EditValueChanged(object sender, EventArgs e)
        {
            try
            {
                var luc = (GridLookUpEdit)sender;
                var stock = (ItemStock)gvStock.GetFocusedRow();
                var item = (ItemMaster)luc.Properties.View.GetFocusedRow();
                if (item != null && stock != null)
                {
                    stock.ItemMaster = item;
                    stock.ItemId = item.ItemId;
                    gvStock.RefreshData();
                }
            }
            catch (Exception ex)
            {
                _oCommFn.TryCatchErrorMsg(ex.Message);
            }
        }


        public bool OperationSave()
        {
            try
            {
                gvStock.PostEditor();
                if (IsValid())
                {
                    if ((Mode == ClsGlobalVarz.Mode.Add || Mode == ClsGlobalVarz.Mode.Edit) &&
                        _oCommFn.ValidateCrud(Mode))
                    {
                        using (var ts = new TransactionScope())
                        {
                            OperationItemStock();
                            OperationStockLedger();
                            ts.Complete();
                        }
                        _oCommFn.MsgBoxCrud(Mode);
                        return true;
                    }
                    else if (Mode != ClsGlobalVarz.Mode.Add && Mode != ClsGlobalVarz.Mode.Edit)
                    {
                        _oCommFn.WarningMsg("Check Mode");
                        return false;
                    }
                }
                return false;
            }
            catch (Exception ex)
            {
                _oCommFn.TryCatchErrorMsg(ex.Message);
                return false;
            }
        }
        private void OperationItemStock()
        {
            using (var context = new AccManagerEntities())
            {
                foreach (var stock in _lstItemStock)
                {
                    var oItemStock = new ItemStock();
                    if (Mode == ClsGlobalVarz.Mode.Add)
                    {
                        oItemStock.StockId = maxStkId;
                        oItemStock.StockCode = txtStockCode.Text;
                    }
                    else if (Mode == ClsGlobalVarz.Mode.Edit)
                    {
                        oItemStock = context.ItemStocks.Single(x => x.StockId == stock.StockId);
                        lstOpenStock.Remove(lstOpenStock.Single(x => x.StockId == oItemStock.StockId));
                    }

                    stock.StockId = oItemStock.StockId;
                    oItemStock.ItemId = stock.ItemId;
                    oItemStock.Received = stock.Received;
                    oItemStock.Rate = stock.Rate;
                    oItemStock.TransType = "OP";
                    oItemStock.Remarks = stock.Remarks;

                    if (Mode == ClsGlobalVarz.Mode.Add)
                        context.ItemStocks.Add(oItemStock);
                    context.SaveChanges();
                }

                if (Mode == ClsGlobalVarz.Mode.Edit)
                {
                    foreach (var stock in lstOpenStock)
                    {
                        context.ItemStocks.Remove(context.ItemStocks.Single(x => x.StockId == stock.StockId));
                        context.StockLedgers.Remove(context.StockLedgers.Single(x => x.TransId == stock.StockId && x.TransType == "OP"));
                        context.SaveChanges();
                    }
                }
            }
        }
        private void OperationStockLedger()
        {
            using (var context = new AccManagerEntities())
            {
                foreach (var stock in _lstItemStock)
                {
                    var oStockLedger = new StockLedger();
                    if (Mode == ClsGlobalVarz.Mode.Add)
                    {
                        oStockLedger.StkLedgerId = context.StockLedgers.ToList().Count > 0
                            ? context.StockLedgers.Max(x => x.StkLedgerId) + 1 : 1;
                    }
                    else if (Mode == ClsGlobalVarz.Mode.Edit)
                    {
                        oStockLedger = context.StockLedgers.Single(x => x.TransId == stock.StockId && x.TransType == "OP");
                    }

                    oStockLedger.ItemId = stock.ItemId;
                    oStockLedger.Received = stock.Received;
                    oStockLedger.Particular = String.Format("From Item Opening Stock To {0}", lucStores.Text);
                    oStockLedger.TransType = "OP";
                    oStockLedger.StoreId = lucStores.Value;
                    oStockLedger.TransDate = DateTime.Now;
                    oStockLedger.TransId = stock.StockId;
                    oStockLedger.Remarks = stock.Remarks;

                    if (Mode == ClsGlobalVarz.Mode.Add)
                        context.StockLedgers.Add(oStockLedger);
                    context.SaveChanges();
                }
            }
        }


        public void OperationOpen()
        {
            try
            {
                gclOpen.BringToFront();
                var context = new AccManagerEntities();
                var lstItemStock = context.ItemStocks.Where(x => x.TransType == "OP").ToList();
                var lstStockLedger = context.StockLedgers.Where(x => x.TransType == "OP").ToList();
                var lst = from iStk in lstItemStock
                          join sl in lstStockLedger
                              //on iStk.ItemId equals stk.ItemId
                              on new { a = (long?)iStk.ItemId, b = iStk.StockId } equals new { a = sl.ItemId, b = sl.TransId } into stockList
                          from stk in stockList
                          select new { stk.ItemId, stk.ItemMaster, stk.StoreId, stk.StoreMaster };

                var stocklist = lst.GroupBy(x => new { x.ItemId, x.StoreId }).Select(x => new
                {
                    x.FirstOrDefault().ItemId,
                    x.FirstOrDefault().ItemMaster,
                    x.FirstOrDefault().StoreId,
                    x.FirstOrDefault().StoreMaster
                }).ToList();
                gcStockSearch.DataSource = stocklist;
            }
            catch (Exception ex)
            {
                _oCommFn.TryCatchErrorMsg(ex.Message);
            }
        }
        private void gvStockSearch_DoubleClick(object sender, EventArgs e)
        {
            try
            {
                itemId = Convert.ToInt64(gvStockSearch.GetFocusedRowCellValue(gColItemId));
                var storeId = Convert.ToInt64(gvStockSearch.GetFocusedRowCellValue(gColStoreId));

                var context = new AccManagerEntities();
                lstOpenStock = new List<ItemStock>(context.ItemStocks.Where(x => x.ItemId == itemId
                                                             && x.StockLedgers.FirstOrDefault().StoreId == storeId).ToList());
                _lstItemStock = new BindingList<ItemStock>((List<ItemStock>)_oCommFn.Clone(lstOpenStock));
                gcStock.DataSource = _lstItemStock;
                gvStock.RefreshData();
                lucStores.EditValue = storeId;
                txtStockCode.Text = null;
                lblStockCode.Visible = false;
                txtStockCode.Visible = false;
                gColItemName.OptionsColumn.AllowEdit = false;

                gvStock.OptionsView.NewItemRowPosition = NewItemRowPosition.None;
                _oCommFn.DisableControls(gclMain, true);
                gclMain.BringToFront();
            }
            catch (Exception ex)
            {
                _oCommFn.TryCatchErrorMsg(ex.Message);
            }
        }

        public void OperationEdit()
        {
            if (_oCommFn.ValidateOpenRecord(itemId))
            {
                _oCommFn.DisableControls(gclMain, false);
                SetMode(ClsGlobalVarz.Mode.Edit);
            }
        }
        public bool OperationDelete()
        {
            try
            {
                if (_oCommFn.ValidateOpenRecord(itemId))
                {
                    SetMode(ClsGlobalVarz.Mode.Delete);
                    if (_oCommFn.ValidateCrud(Mode))
                    {
                        using (var context = new AccManagerEntities())
                        {
                            using (var ts = new TransactionScope())
                            {
                                foreach (var item in lstOpenStock)
                                {
                                    var itemStock = context.ItemStocks.Single(x => x.StockId == item.StockId);
                                    context.ItemStocks.Remove(itemStock);
                                    var stockLedger = context.StockLedgers.Single(x => x.TransId == item.StockId && x.TransType == "OP");
                                    context.StockLedgers.Remove(stockLedger);
                                    context.SaveChanges();
                                }
                                ts.Complete();
                            }
                            _oCommFn.MsgBoxCrud(Mode);
                        }
                        return true;
                    }
                }
                return false;
            }
            catch (Exception ex)
            {
                _oCommFn.TryCatchErrorMsg(ex.Message);
                return false;
            }
        }

        public void ResetData()
        {
            _oCommFn.ClearFields(this);
            _oCommFn.DisableControls(gclMain, false, ClsGlobalVarz.Mode.Add);
            gclMain.BringToFront();
            SetMode(ClsGlobalVarz.Mode.Add);
            _lstItemStock.Clear();
            lstOpenStock.Clear();
            gcStock.DataSource = null;
            gcStock.DataSource = _lstItemStock;
            gvStock.RefreshData();
            itemId = 0;
            gvStock.OptionsView.NewItemRowPosition = NewItemRowPosition.Bottom;
            SetStockCode();
            lblStockCode.Visible = true;
            txtStockCode.Visible = true;
            gColItemName.OptionsColumn.AllowEdit = true;
        }
        public bool IsValid()
        {
            ccDxValidationProvider1.Validate();
            return ccDxValidationProvider1.GetInvalidControls().Count <= 0;
        }


        private void repTEQty_KeyPress(object sender, KeyPressEventArgs e)
        {
            //TODO: Write Keypress Code;
            //_oCommFn.
        }
        private void gvStock_KeyDown(object sender, KeyEventArgs e)
        {
            try
            {
                if (e.KeyData == Keys.Delete && Mode != ClsGlobalVarz.Mode.Open)
                {
                    var rowhandle = gvStock.FocusedRowHandle;
                    if (rowhandle > -1)
                        gvStock.DeleteRow(rowhandle);
                }
            }
            catch (Exception ex)
            {
                _oCommFn.TryCatchErrorMsg(ex.Message);
            }
        }

        private void lucStores_EditValueChanged(object sender, EventArgs e)
        {
            ccDxValidationProvider1.RemoveControlError(lucStores);
        }
    }
}
